package com.stylefeng.guns.modular.system.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.cache.CacheKit;
import com.stylefeng.guns.core.common.Tools.Result;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.constant.dictmap.OrgDict;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.node.List2ZTree;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.Dict;
import com.stylefeng.guns.modular.system.model.Org;
import com.stylefeng.guns.modular.system.model.UserCw;
import com.stylefeng.guns.modular.system.service.IDictService;
import com.stylefeng.guns.modular.system.service.IOrgService;
import com.stylefeng.guns.modular.system.service.IUserCwService;
import com.stylefeng.guns.modular.system.warpper.OrgWarpper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 组织管理控制器
 *
 * @author fengshuonan
 *
 * @Date 2018-08-24 11:48:38
 */
@Controller
@RequestMapping(value={"/gunsApi/auth/org"})
@Api(value="组织机构相关api",tags={"组织机构操作接口"})
public class OrgController extends BaseController {

    private String PREFIX = "/system/org/";

    @Autowired
    private IOrgService orgService;
    
    
    @Autowired
    private IUserCwService userCwService;
    
    @Autowired
    private IDictService dictService;

    /**
     * 跳转到组织管理首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "org.html";
    }

    /**
     * 跳转到添加组织管理
     */
    @RequestMapping("/org_add")
    public String orgAdd() {
      return PREFIX + "org_add.html";
    }

    /**
     * 跳转到修改组织管理
     */
    @RequestMapping("/org_update/{orgId}")
    public String orgUpdate(@PathVariable Integer orgId, Model model) {
        Org org = orgService.selectById(orgId);
        model.addAttribute("item",org);
        LogObjectHolder.me().set(org);
        return PREFIX + "org_edit.html";
    }

    /**
     * 获取字典表code子类列表
     * @param code 字典表code编码
     */
    @ApiOperation(value="获取字典表code子类列表",tags={"获取字典表code子类列表"},notes = "获取平台定义字典表,参数为必填，对应大类的code值",httpMethod ="GET" )
    @GetMapping(value = "/dict")
    @ResponseBody
    public Result dict(@ApiParam(name = "code", value = "依据code值获取字典表列表,code参数必填", required = false) @RequestParam(value = "code",required = false) String code) {
        List<Dict> list = new ArrayList<>();
        if(StringUtils.isNotBlank(code)){
            list=ConstantFactory.me().findInDictByCode(code);
        }else{
            list=this.dictService.selectList(new EntityWrapper<>());
        }
        return Result.success(list);
    }

    /**
     * 获取部门的tree列表
     */
    @ApiOperation("获取组织机构树列表")
    @RequestMapping(value = "/tree",method = RequestMethod.POST)
    @ResponseBody
    public Result tree(@ApiParam(name = "soName",value = "机构名称(模糊查询)") @RequestParam(value = "soName",required = false) String soName) {
        List<ZTreeNode> tree = this.orgService.tree(soName);
        return Result.success(List2ZTree.toTree02(tree));
    }

    /**
     * 获取组织管理列表
     */
    @ApiOperation(value="获取组织机构列表",notes = "获取组织机构列表",httpMethod ="GET")
    @GetMapping(value = "/list")
    @ResponseBody
    public Result list(@ApiParam(name = "condition", value = "查询条件(机构名称或机构拼音)", required = false) @RequestParam(value = "condition",required = false) String condition,
                       @ApiParam(name = "so_Id", value = "机构ID", required = false) @RequestParam(value = "so_Id",required = false) String so_Id,
                       @ApiParam(name = "soCate", value = "机构分类(1:运营单位 2:客运单位 3:合作单位)", required = false) @RequestParam(value = "soCate",required = false) String soCate,
                       @ApiParam(name = "soType", value = "机构类型(1:机构 2:部门)", required = false) @RequestParam(value = "soType",required = false) String soType,
                       @ApiParam(name = "pageNum", value = "当前页数", required = false) @RequestParam(value = "pageNum",defaultValue = "1",required = false) Integer pageNum,
                       @ApiParam(name = "pageSize", value = "每页显示条数", required = false) @RequestParam(value = "pageSize", defaultValue = "10000",required = false) Integer pageSize
                       ) {
        
        Page<Org> page = new Page<>(pageNum,pageSize);
        Wrapper<Org> wrapper=new EntityWrapper<>();
        String accout=this.getShiroUser().getAccount();
        int soId = 0;
        if (StringUtils.isBlank(so_Id)) {
            if (StringUtils.isNotEmpty(accout) && !StringUtils.equalsIgnoreCase("admin", accout)) {
                soId = getShiroUser().getSoId();
            if (ToolUtil.isNotEmpty(soId)) {
                wrapper.eq("so_id", soId).or();
                 wrapper.like("so_pids", "%[" + soId + "]%");
            }
            }
        }else{
            wrapper.like("so_pids", "%[" + so_Id + "]%");
    }
        
        if(StringUtils.isNotBlank(condition)){
            wrapper.like("so_name",condition).or();
            wrapper.like("so_name_py",condition);
        }
        if(StringUtils.isNotBlank(soCate)){
            if(StringUtils.isNotBlank(soType)&&StringUtils.equals("1", soType))
                wrapper.and().eq("so_cate", soCate);
        }
        if(StringUtils.isNotEmpty(soType)){
            wrapper.and().eq("so_type", soType);
        }
        page= this.orgService.selectPage(page,wrapper);
        List<Org> list = page.getRecords();
        Collections.sort(list,Comparator.comparing(Org::getSoLevel).thenComparing(Org::getSoSort));
        List<Map<String, Object>> mList=new ArrayList<>();
        for (Org o:list){
            if(o.getSoId().equals(soId))
                o.setSoPid(0);
            Map map= BeanUtil.beanToMap(o);
          mList.add(map);
        }
        super.warpObject(new OrgWarpper(mList));
        BeanUtil.setFieldValue(page,"records",mList);
    return Result.success(page);
     }

    /**
     * 新增组织管理
     */
    @ApiOperation(value="添加组织机构",notes = "添加组织机构",httpMethod ="POST")
    @BussinessLog(value = "添加组织", key = "soName", dict = OrgDict.class)
    @RequestMapping(value = "/add",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Result add(@Valid @RequestBody @ApiParam(name = "org", value = "添加组织机构", required = true) Org org, BindingResult result) {
        if (result.hasErrors()) {
            return Result.error(BizExceptionEnum.REQUEST_NULL);
        }

        if (ToolUtil.isOneEmpty(org, org.getSoName())) {
            return Result.error(BizExceptionEnum.REQUEST_NULL);
        }
        //完善pids,根据pid拿到pid的pids
        deptSetPids(org);
        Wrapper<Org> wrapper=new EntityWrapper<>();
        wrapper.eq("so_name",org.getSoName()).and();
        wrapper.eq("so_type",org.getSoType()).and();
        wrapper.eq("so_cate",org.getSoCate());
        List<Org> list = this.orgService.selectList(wrapper);
        if (!list.isEmpty()){//机构已存在
            return Result.error(BizExceptionEnum.ORG_ALREADY_EXISTS);
         }
      String soType=org.getSoType();
      if (StringUtils.equals("1", soType)) {
        Integer pid = org.getSoPid();
        BB:
        while (true) {
            if (ToolUtil.isNotEmpty(pid)) {
                Org porg = this.orgService.selectById(pid);
            if (porg != null) {
                if (StringUtils.equals("2", porg.getSoType())) { // 部门下不能添加机构
                    throw new GunsException(BizExceptionEnum.ORG_ADD_HAS_DEP); // 遍历上级 存在部门 抛出异常
            } else {
              pid = porg.getSoPid();
              continue BB;
                }
          }
        }
        break;
      }
    }
    Boolean b=false;
    try{
       b= this.orgService.insert(org);
        }catch (Exception e){
            throw new GunsException(BizExceptionEnum.EXISTS_THIS_ORG);
    }
    String msg="插入机构失败";
    if (b)
        msg="插入机构成功!";

     return Result.success(msg);
    }

    /**
     * 删除组织管理
     */
    @ApiOperation(value="删除组织机构",notes = "删除组织机构",httpMethod ="DELETE")
    @BussinessLog(value = "删除组织机构", key = "orgId", dict = OrgDict.class)
    @RequestMapping(value = "/delete",method = RequestMethod.DELETE)
    @ResponseBody
   public Result delete(@ApiParam(name = "orgId", value = "机构对象ID", required = true)  @RequestParam("orgId") Integer orgId) {
        LogObjectHolder.me().set(ConstantFactory.me().getOrgName(orgId));
        Org org=this.orgService.selectById(orgId);
        if(org==null){
            return Result.error(BizExceptionEnum.ORG_NOT_EXISTS);
        }
        //判断机构下是否有子机构
        Wrapper<Org> wrapper=new EntityWrapper<>();
        wrapper.like("so_pids",orgId+"");
        List<Org> oList=this.orgService.selectList(wrapper);
        if(!oList.isEmpty()){
            return Result.error(BizExceptionEnum.ORG_HAS_SON);
        }
        //判断机构下是否有人 有人不能删除
        UserCw userCw=new UserCw();
        userCw.setSoId(orgId);
        List<UserCw> uList=this.userCwService.selectList(new EntityWrapper<>(userCw));
        if(!uList.isEmpty()){
            return Result.error(BizExceptionEnum.ORG_HAS_USERS);
        }
        this.orgService.deleteOrg(orgId);
        return Result.success();
    }

    /**
     * 修改组织管理
     */
    @RequestMapping("/update")
    @ResponseBody
    @ApiOperation(value="组织机构对象更新",notes = "组织机构对象更新",httpMethod ="POST" )
    @ApiImplicitParam(name = "org", value = "组织机构详细实体org", required = true, dataType = "Org")
    public Result update(@ApiParam(name = "org", value = "机构对象", required = true) @RequestBody Org org) {
    // 由机构修改为部门  如果原机构下有机构  不能修改
    if (StringUtils.equals("2", org.getSoType())) {
        Wrapper<Org> wrapper=new EntityWrapper<>();
        wrapper.like("so_pids",org.getSoId()+"");
        List<Org> orgList = this.orgService.selectList(wrapper);
        if (!orgList.isEmpty()) {
            List<Org> demorm = orgList .stream().filter(demo -> StringUtils.equals("1", demo.getSoType())).distinct().collect(Collectors.toList());
        if (!demorm.isEmpty()) {
            return Result.error(BizExceptionEnum.ORG_MDY_HAS_USERS);
            }
         }
        }else{
        //由部门修改为机构  如果部门上级存在部门  不让修改
        Integer pid=org.getSoPid();
        while(true){
        if (ToolUtil.isNotEmpty(pid)) {
            Org porg = this.orgService.selectById(pid);
          if (porg != null) {
            if (StringUtils.equals("2", porg.getSoType())) { // 机构上存在部门 不能修改
              return Result.error(BizExceptionEnum.ORG_MDY_HAS_DEP); // 遍历上级 存在部门 抛出异常
            }else{
                pid=porg.getSoPid();
            }
          }
        }
         break;
        }
    }
    //判断机构或部门不能挂载在子孙节点上
        Wrapper<Org> wrapper=new EntityWrapper<>();
        wrapper.like("so_pids",org.getSoId()+"");
        List<Org> orgList = this.orgService.selectList(wrapper);
        if(!orgList.isEmpty()){//存在下级机构数据
            List<Integer> pidList=orgList.stream().sorted(Comparator.comparing(Org::getSoId)).map(Org::getSoId).collect(Collectors.toList());
            if(pidList.contains(org.getSoPid()))
                return Result.error(BizExceptionEnum.ORG_MDY_ON_LA); //机构不能挂载在子孙节点上
        }
        deptSetPids(org);
        org.updateAllColumnById();
        if(!orgList.isEmpty()){
            orgList.forEach(o->{
                deptSetPids(o);
                orgService.updateById(o);
            });
        }
        return Result.success("机构修改成功!");
    }

    /**
     * 组织管理详情
     */
    @ApiOperation(value="获取组织管理详情",httpMethod="GET")
    @ApiImplicitParam(name = "orgId", value = "机构ID", required = true, dataType = "String", paramType = "query")
    @RequestMapping(value = "/detail",method = RequestMethod.GET)
    @ResponseBody
    public Result detail(@ApiParam(name = "orgId", value = "根据orgId获取组织机构明细", required = true) @RequestParam("orgId") Integer orgId) {
        Org org=orgService.selectById(orgId);
        if(ToolUtil.isEmpty(org)){
           return Result.error(BizExceptionEnum.ORG_NOT_EXISTS);
        }
        return Result.success(super.warpObject(new OrgWarpper(new ArrayList<Map<String, Object>>(){{
            add(BeanUtil.beanToMap(org));
        }})));
    }



    private void deptSetPids(Org org) {
        if (ToolUtil.isEmpty(org.getSoPid()) || org.getSoPid().equals(0)) {
            org.setSoPid(0);
            org.setSoPids("[0],");
            org.setSoLevel(1);
        } else {
            int pid = org.getSoPid();
            Org temp = orgService.selectById(pid);
            Integer pLevels = temp.getSoLevel();
            org.setSoLevel(pLevels + 1);
            String pids = temp.getSoPids();
            org.setSoPid(pid);
            org.setSoPids(pids + "[" + pid + "],");
        }
    }

    @Cacheable(value="local",key = "'userCw_'+#result.getId()")
    public  ShiroUser getShiroUser(){
        String token= getHttpServletRequest().getHeader("Authorization").substring(7);
        return CacheKit.get(CACHE_STRATEGY,token);
    }
}
